import { Graph, Shape, Addon, FunctionExt } from '@antv/x6'
import './shape'

export default class FlowGraph {
    // 初始化画布
    static init() {
        this.graph = new Graph({
            container: document.getElementById('Container'),
            width: 1100,
            height: 700,
            grid: {
                size: 10,
                visible: true,
                type: 'mesh',
                args: [
                    {
                        color: '#e5e5e5',
                        thickness: 1,
                        factor: 4,
                    }]
            },
            // 滚动功能
            scroller: {
                enabled: true,
                pageVisible: true,
                pageBreak: true,
                pannable: false
            },
            // 滚轮缩放
            mousewheel: {
                enabled: true,
                modifiers: ['ctrl', 'meta'],
                minScale: 0.5,
                maxScale: 2
            },
            // 框选功能
            selecting: {
                enabled: true,
                multiple: true,
                rubberband: true,
                movable: true,
                showNodeSelectionBox: true
            },
            // 配置全局的连线
            connecting: {
                anchor: 'center',
                connectionPoint: 'anchor',
                allowBlank: false,
                highlight: true,
                snap: true,
                // 连线的样式
                createEdge() {
                    return new Shape.Edge({
                        attrs: {
                            line: {
                                stroke: '#5F95FF',
                                strokeWidth: 1,
                                targetMarker: {
                                    name: 'classic',
                                    size: 8
                                }
                            }
                        },
                        router: {
                            name: 'manhattan'
                        },
                        zIndex: 0
                    })
                },
                // 连线校验
                validateConnection({
                                       sourceView,
                                       targetView,
                                       sourceMagnet,
                                       targetMagnet
                                   }) {
                    if (sourceView === targetView) {
                        return false
                    }
                    if (!sourceMagnet) {
                        return false
                    }
                    if (!targetMagnet) {
                        return false
                    }
                    return true
                }
            },
            // 连接高亮
            highlighting: {
                magnetAvailable: {
                    name: 'stroke',
                    args: {
                        padding: 4,
                        attrs: {
                            strokeWidth: 4,
                            stroke: 'rgba(223,234,255)'
                        }
                    }
                }
            },
            // 键盘快捷键
            keyboard: {
                enabled: true
            },
            // 对齐线
            snapline: true,
            // 画布撤销/重做
            history: true,
            // 剪切板
            clipboard: {
                enabled: true
            }
        })
        this.initStencil()
        this.initShape()
        this.initEvent()
        return this.graph
    }
    // 初始化拖拽侧边栏
    static initStencil () {
        this.stencil = new Addon.Stencil({
            title: '故障树',
            target: this.graph,
            // 搜索功能
            search(cell, keyword) {
                return cell.shape.indexOf(keyword) !== -1
            },
            stencilGraphWidth: 280,
            collapsable: true,
            // 分组
            groups: [
                {
                    name: 'event',
                    title: '事件',
                    graphHeight: 180
                },
                {
                    name: 'logic',
                    title: '逻辑门',
                    layoutOptions: {
                        columns: 2,
                        marginX: 0
                    },
                    graphHeight: 270
                },
                // {
                //     name: 'group',
                //     title: '节点组',
                //     graphHeight: 100,
                //     layoutOptions: {
                //         columns: 1,
                //         marginX: 60
                //     }
                // }
            ]
        })
        const stencilContainer = document.querySelector('#Stencil')
        stencilContainer.appendChild(this.stencil.container)
    }
    // 初始化拖拽的图形
    static initShape() {
        const {graph} = this
        // 顶事件/中间事件
        const r1 = graph.createNode({
            shape: 'flow-chart-rect',
            attrs: {
                text: {
                    textWrap: {
                        text: '顶/中间事件'
                    }
                }
            }
        })
        // 底事件
        const r2 = graph.createNode({
            shape: 'flow-chart-rect',
            width: 70,
            height: 70,
            attrs: {
                body: {
                    rx: 35,
                    ry: 35
                },
                text: {
                    textWrap: {
                        text: '底事件'
                    }
                }
            }
        })
        // 条件事件
        const r3 = graph.createNode({
            shape: 'flow-chart-rect',
            attrs: {
                body: {
                    rx: 24,
                    ry: 24
                },
                text: {
                    textWrap: {
                        text: '条件事件'
                    }
                }
            }
        })
        // 未探明事件
        const r4 = graph.createNode({
            shape: 'flow-chart-rect',
            width: 52,
            height: 52,
            angle: 45,
            attrs: {
                'edit-text': {
                    style: {
                        transform: 'rotate(-45deg)'
                    }
                },
                text: {
                    textWrap: {
                        text: '未探明事件'
                    },
                    transform: 'rotate(-45deg)'
                }
            },
            ports: {
                groups: {
                    top: {
                        position: {
                            name: 'top',
                            args: {
                                dx: -26
                            }
                        }
                    },
                    right: {
                        position: {
                            name: 'right',
                            args: {
                                dy: -26
                            }
                        }
                    },
                    bottom: {
                        position: {
                            name: 'bottom',
                            args: {
                                dx: 26
                            }
                        }
                    },
                    left: {
                        position: {
                            name: 'left',
                            args: {
                                dy: 26
                            }
                        }
                    }
                }
            }
        })
        // 非门
        const r5 = graph.createNode({
            shape: 'flow-chart-rect',
            width: 50,
            height: 50,
            attrs: {
                body: {
                    rx: 25,
                    ry: 25,
                },
                text: {
                    textWrap: {
                        text: '非门'
                    }
                }
            }
        })
        // 与门
        const c1 = graph.createNode({
            shape: 'flow-chart-image1',
            ports: {
                groups: {
                    top: {
                        position: {
                            name: 'top',
                            args: {
                                dx: -0.1
                            }
                        },
                    },
                    bottom: {
                        position: {
                            name: 'bottom',
                            args: {
                                dx: -0.1
                            }
                        }
                    }
                }
            }
        })
        // 或门
        const c2 = graph.createNode({
            shape: 'flow-chart-image2',
            ports: {
                groups: {
                    top: {
                        position: {
                            name: 'top',
                            args: {
                                dx: -0.1
                            }
                        },
                    },
                    bottom: {
                        position: {
                            name: 'bottom',
                            args: {
                                dx: -0.1,
                                dy: -7
                            }
                        }
                    }
                }
            }
        })
        // 转移门
        const c3 = graph.createNode({
            shape: 'flow-chart-image3',
            ports: {
                groups: {
                    top: {
                        position: {
                            name: 'top',
                            args: {
                                dx: -0.1
                            }
                        },
                    },
                    bottom: {
                        position: {
                            name: 'bottom',
                            args: {
                                dx: -0.1
                            }
                        }
                    },
                    right: {
                        position: {
                            name: 'right',
                            args: {
                                dx: -12
                            }
                        }
                    },
                    left: {
                        position: {
                            name: 'left',
                            args: {
                                dx: 12
                            }
                        }
                    }
                }
            }
        })
        // 禁门
        const c4 = graph.createNode({
            shape: 'flow-chart-image4',
            ports: {
                groups: {
                    top: {
                        position: {
                            name: 'top',
                            args: {
                                dx: -0.1
                            }
                        },
                    },
                    bottom: {
                        position: {
                            name: 'bottom',
                            args: {
                                dx: -0.1
                            }
                        }
                    }
                }
            }
        })
        this.stencil.load([r1, r2, r3], 'event')
        this.stencil.load([c1, c2, r5, c3, c4], 'logic')
    }
    // 显示/隐藏连接桩
    static showPorts(ports, show) {
        for (let i = 0, len = ports.length; i < len; i = i + 1) {
            ports[i].style.visibility = show ? 'visible' : 'hidden'
        }
    }
    // 初始化事件
    static initEvent() {
        const {graph} = this
        const container = document.getElementById('Container')
        // 点击鼠标右键来编辑节点内的文字
        graph.on('node:contextmenu', ({cell, view}) => {
            const oldText = cell.attr('text/textWrap/text')
            const elem = view.container.querySelector('.x6-edit-text')
            if (elem == null) {
                return
            }
            cell.attr('text/style/display', 'none')
            if (elem) {
                elem.style.display = ''
                elem.contentEditable = 'true'
                elem.innerText = oldText
                elem.focus()
            }
            const onBlur = () => {
                cell.attr('text/textWrap/text', elem.innerText)
                cell.attr('text/style/display', '')
                elem.style.display = 'none'
                elem.contentEditable = 'false'
            }
            elem.addEventListener('blur', () => {
                onBlur()
                elem.removeEventListener('blur', onBlur)
            })
        })
        // 鼠标进入节点中显示连接桩
        graph.on(
            'node:mouseenter',
            FunctionExt.debounce(() => {
                const ports = container.querySelectorAll(
                    '.x6-port-body'
                )
                this.showPorts(ports, true)
            }),
            500
        )
        // 鼠标离开节点后不显示连接桩
        graph.on('node:mouseleave', () => {
            const ports = container.querySelectorAll(
                '.x6-port-body'
            )
            this.showPorts(ports, false)
        })
        // 按下delete键删除当前节点
        graph.bindKey('delete', () => {
            const cells = graph.getSelectedCells()
            if (cells.length) {
                graph.removeCells(cells)
            }
        })
    }
    // 清空画布
    static destroy() {
        this.graph.dispose()
    }
}
